﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.Mvc;
using System.Web.Mvc.Html;
using System.Web.Routing;
using System.Linq.Expressions;

namespace Lilium.Web.Mvc.Html
{
	/// <summary>
	/// HtmlHelper extensions backed by EntityController
	/// </summary>
	public static class EntityControllerExtensions
	{
		public static MvcHtmlString OrderByActionLink<TModel, TEntity, TValue>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TEntity, TValue>> expression)
			where TModel : IEnumerable<TEntity>
		{
			var memebrAcess = (MemberExpression)expression.Body; 
			var lambda = Expression.Lambda<Func<TModel, TValue>>(memebrAcess, Expression.Parameter(typeof(TModel), "model"));
			var metadata = ModelMetadata.FromLambdaExpression(lambda, htmlHelper.ViewData);

			//TODO: интегрировать с контроллером
			return htmlHelper.ActionLink(metadata.DisplayName ?? metadata.PropertyName, "OrderBy", new { propertyPath = GetMemberPath(memebrAcess) });
		}

		public static MvcHtmlString OrderByActionLink<TModel, TEntity, TValue>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TEntity, TValue>> expression, string linkText)
			where TModel : IEnumerable<TEntity>
		{
			var memebrAcess = (MemberExpression)expression.Body;
			//var lambda = Expression.Lambda<Func<TModel, TValue>>(memebrAcess, Expression.Parameter(typeof(TModel), "model"));
			//var metadata = ModelMetadata.FromLambdaExpression(lambda, htmlHelper.ViewData);

			//TODO: интегрировать с контроллером
			return htmlHelper.ActionLink(linkText, "OrderBy", new { propertyPath = GetMemberPath(memebrAcess) });
		}
		/* можно размещать ссылку напрямую на метод контроллера.
		public static MvcHtmlString EditorForActionLink<TModel, TValue>(this HtmlHelper<TModel> htmlHelper, string linkText, Expression<Func<TModel, TValue>> expression)
		{
			if (htmlHelper == null) throw new ArgumentNullException("htmlHelper");
			if (expression == null) throw new ArgumentNullException("expression");

			var entityController = htmlHelper.ViewContext.Controller as IEntityController;

			if (entityController == null)
				throw new InvalidOperationException(string.Format("Editor for model action link requires an entity controller."));

			var entity = expression.Compile()(htmlHelper.ViewData.Model);

			var actionDescription = entityController.GetActionDescription(EntityActionType.EditorView, entity);

			var routeValues = new RouteValueDictionary();
			routeValues.AddEntityKey(entity, actionDescription);

			return htmlHelper.ActionLink(linkText, actionDescription.ActionName, routeValues);
		}
		*/
		private static string GetMemberPath(MemberExpression memberExpression)
		{
			var pathBuilder = new StringBuilder();
			GetMemberPath(memberExpression, pathBuilder);
			return pathBuilder.ToString();
		}

		private static void GetMemberPath(MemberExpression memberExpression, StringBuilder pathBuilder)
		{
			if (memberExpression == null) throw new ArgumentNullException("memberExpression");
			if (pathBuilder == null) throw new ArgumentNullException("pathBuilder");

			var next = memberExpression.Expression as MemberExpression;
			if (next != null)
			{
				GetMemberPath(next, pathBuilder);
				pathBuilder.Append('.');
			}
			pathBuilder.Append(memberExpression.Member.Name);
		}
	}
}